#include "thread.hpp"

using namespace threadModule;
#include <vector>
#define num 10
static int ticketNum = 100; // 假设有100张票// 现在 kicket就是临界资源

// zdl:: 现在我们开始使用 mutex来给临界资源上锁
// 锁本身就是全局的， 那么锁也是共享资源，zdl:: 所以谁来保证锁的安全？？？？？
// zdl:: 答案就是 所在设计时就被设计为原子的
// zdl:: 不能对大块的代码枷锁！

// 2. 我们可以怎么来理解锁这个设计呢
// 2.1 锁的本质其实就是对资源的一种预定机制
// 2.2 一旦一个资源已经被申请过了，其他的线程就只能进行阻塞等待
// 2.4 线程在访问临界区的时候可以被切换
// 2.5 线程在进行切换的时候别人可以进来不！！不能，
// 这也是我们在访问临界资源时效率低下的原因， 原子性
// 2.5 不遵守这样的约定嗯可以不？？ 是可以的， 但是会有bug
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class ThreadData
{
public:
    std::string name;
    pthread_mutex_t *lock_ptr;
};

void ticket(ThreadData& td)
{
    while (true)
    {
        pthread_mutex_lock(&lock); // 上锁
        // zdl:: 进行这样的操作后就是每一个线程都必须先申请锁

        // 下面的代码就是我们说的临界区
        if (ticketNum > 0)
        {
            // 抢票
            usleep(1000); // 模拟处理时间
            printf("get a new ticket , who get it :%s ,id = %d\n", td.name.c_str(), ticketNum--);
        }
        // 2. 入库
        else
        {
            // 没票了，退出循环
            printf("no ticket left!\n");
            pthread_mutex_unlock(&lock); // 解锁

            break;
        }
        pthread_mutex_unlock(&lock); // 解锁
    }
}

int main()
{

    pthread_mutex_t lock;
    pthread_mutex_init(&lock, nullptr);
    std::vector<Thread<ThreadData&>> threads;
    ThreadData td;
    td.lock_ptr = &lock;
    for (int i = 0; i < num; i++)
    {
        auto td = new ThreadData();
        td->lock_ptr = &lock;
        threads.emplace_back(ticket, *td);
        td->name = threads.back().getName();
    }

    for (auto &t : threads)
    {
        t.Running();
    }
    sleep(10);
    for (auto &t : threads)
    {
        t.join();
    }

    pthread_mutex_destroy(&lock);
    return 0;
}

// using namespace std;

// int main()
// {

//     int n; cin >> n;
//     cout << "You entered: " << n << endl;
//     return 0;
// }

// zdl:: 进行原子性的调度，现在我需要弄弄清楚什么是原子操作
// 时间片的耗尽
// 更高优先级级的进行，会进行切换
// zdl:: 什么时候票数会不降反增

// 什么时候会出现这样的问题，我还是需要个报告更加细致的研究这样的问题才行
// 什么时候我的打字准确率才能达到一个较高的水平呢？

// zdl: 出现上面的问题之后我们要做那么来解决这样的问题

// 锁的概念就被提了出来

// zdl:: 我们所有的抱回都是对临界区资源的保护，我们就是通过对临界区的代码来访问了临界资源
